package com.xyy.saas.payment.adpater.fumin.spring;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fbank.openapi.sdk.client.FBankOpenApiResponseUnifyClient;
import com.xyy.saas.payment.adpater.fumin.client.FBankOpenApiClient;
import com.xyy.saas.payment.adpater.fumin.client.OpenParameters;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.util.HttpClientUtil;
import com.xyy.saas.payment.util.JSONUtils;
import com.xyy.saas.payment.util.MD5Util;
import com.xyy.saas.payment.util.RSAUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

@Service
@Slf4j
public class SpringClient implements InitializingBean {
    @Autowired
    private SpringConfiguration springConfiguration;
    @Autowired
    private YBMSpringConfiguration ybmSpringConfiguration;
    @Autowired
    private SpringConfiguration2 springConfiguration2;
    @Autowired
    private YBMSpringConfiguration2 ybmSpringConfiguration2;

    private Map<String, FBankOpenApiClient> clientMap = new HashMap<>(8);
    private Map<String, FBankOpenApiResponseUnifyClient> clientMap2 = new HashMap<>(8);

    /**
     * 发送聚合支付请求
     */
    public TreeMap<String, Object> sendToChannel(JSONObject dataMap, String requestURL, String merchantNo) throws PaymentException {
        TreeMap<String, Object> treeMap = new TreeMap<>();
        //商户编号
        dataMap.put("mchntId", getFBankPayMerchantId(merchantNo));

        try {
            String sign = MD5Util.doEncrypt(dataMap, getFBankPayMD5Key(merchantNo));
            dataMap.put("signature", sign);
            String dataString = JSON.toJSONString(dataMap);
            String reqParams = Base64.encodeBase64String(
                    RSAUtil.encryptByPublicKeyByPKCS1Padding(dataString.getBytes(StandardCharsets.UTF_8), getFBankPayPubKey(merchantNo)));
            String responseBody = HttpClientUtil.xyyHttpPostRequest(requestURL, reqParams, "text/plain; charset=utf-8");
            JSONObject jsonObject = JSON.parseObject(responseBody);

            for(Map.Entry<String, Object> entry : jsonObject.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue().toString();
                treeMap.put(key, value);
            }

            log.info("FuminAdapter#sendToChannel 网关结果，dataString：{}, reqParams：{}, 响应数据：{}", dataString, reqParams, responseBody);
        }
        catch(Exception e) {
            log.error("FuminAdapter#sendToChannel send msg error dataMap:{} requestURL:{}", JSON.toJSONString(dataMap), requestURL, e);
            throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR);
        }

        return treeMap;
    }

    /**
     * 1.0发送企富通请求
     */
    public String send(OpenParameters openParameters, String merchantNo) throws PaymentException {
        try {
            return clientMap.get(merchantNo).send(openParameters);
        }
        catch(Exception ex) {
            log.error("FBankClient#send error, param=" + JSONUtils.toJSON(openParameters), ex);
            throw new PaymentException(ResultCodeEnum.FBANK_SYSTEM_ERROR);
        }
    }

    /**
     * 2.0发送企富通请求
     */
    public String sendUnify(com.fbank.openapi.sdk.client.OpenParameters openParameters, String merchantNo) throws PaymentException {
        try {
            return clientMap2.get(merchantNo).sendUnify(openParameters);
        }
        catch(Exception ex) {
            log.error("FBankClient#sendUnify error, param=" + JSONUtils.toJSON(openParameters), ex);
            throw new PaymentException(ResultCodeEnum.FBANK_SYSTEM_ERROR);
        }
    }

    /**
     * 2.0发送上传文件
     */
    public String uploadFile(com.fbank.openapi.sdk.client.OpenParameters openParameters, String merchantNo) throws PaymentException {
        try {
            return clientMap2.get(merchantNo).uploadFileByFormResponseUnify(openParameters);
        }
        catch(Exception ex) {
            log.error("FBankClient#uploadFile error, param=" + JSONUtils.toJSON(openParameters), ex);
            throw new PaymentException(ResultCodeEnum.FBANK_SYSTEM_ERROR);
        }
    }

    /**
     * 聚合支付公钥
     */
    private String getFBankPayPubKey(String merchantNo) {
        return clientMap.get(merchantNo).getConfig().fBankPayPubKey();
    }

    /**
     * 聚合支付商户号
     */
    private String getFBankPayMerchantId(String merchantNo) {
        return clientMap.get(merchantNo).getConfig().fBankPayMerchantId();
    }

    /**
     * 聚合支付key
     */
    private String getFBankPayMD5Key(String merchantNo) {
        return clientMap.get(merchantNo).getConfig().fBankPayMD5Key();
    }

    @Override
    public void afterPropertiesSet() {
        /**
         * 1.0
         */
        FBankOpenApiClient ykqClient = new FBankOpenApiClient(springConfiguration);
        FBankOpenApiClient ybmClient = new FBankOpenApiClient(ybmSpringConfiguration);
        clientMap.put(springConfiguration.merchantNo(), ykqClient);
        clientMap.put(ybmSpringConfiguration.merchantNo(), ybmClient);

        /**
         * 2.0
         */
        FBankOpenApiResponseUnifyClient ykqClient2 = new FBankOpenApiResponseUnifyClient(springConfiguration2);
        FBankOpenApiResponseUnifyClient ybmClient2 = new FBankOpenApiResponseUnifyClient(ybmSpringConfiguration2);
        clientMap2.put(springConfiguration2.merchantNo(), ykqClient2);
        clientMap2.put(ybmSpringConfiguration2.merchantNo(), ybmClient2);
    }
}
